local desc_1v2 = [[
  # 萌战斗地主模式简介

  ___
  1、游戏开始时，掷骰子决定本局“主教”获得的“恩典”。

  睿智：游戏开始时，你观看所有其他角色的手牌。当你成为其他角色使用【杀】的目标后，你可摸一张牌。

  威光：游戏开始时，你摸一张牌并将此牌明置于恩典牌上。准备阶段，你选择是否用一张牌替换“威光”牌。其他角色使用与“威光”牌花色相同的牌时，若其体力值不大于你，你可令其将一张牌交给你。
  
  神武：游戏开始时，你令其他角色的起始手牌数-1。准备阶段，你可与一名其他角色拼点；若你赢，则你于本回合内造成伤害时，令此伤害+1；若你没赢，你与其各获得对方拼点的牌。
  
  2、每名玩家抽取五名备选角色，“主教”额外抽取三名备选角色。
  
  3、“主教”属于“神谕”阵营；除其之外的角色身份均为“骑士”，属于“天启”阵营。“队列”“围攻”等相关概念在本模式适用。
  
  “主教”的初始体力值与体力上限+1，摸牌阶段额外摸一张牌，获得“恩典”。
  
  4、“骑士”之间手牌不能互通，可“送花”与“砸蛋”。
  
  5、当“骑士”死亡时，另一名“骑士”可选择一项：1.摸两张牌；2.回复1点体力。

  主教死亡或骑士均死亡后游戏结束。
]]
local EV = require "packages/evolution/EV"
local U = require "packages/utility/utility"
-- Because packages are loaded before gamelogic.lua loaded
-- so we can not directly create subclass of gamelogic in the top of lua
local ev_1v2_getLogic = function()
  local ev_1v2_logic = GameLogic:subclass("ev_1v2_logic")

  function ev_1v2_logic:initialize(room)
    GameLogic.initialize(self, room)
    self.role_table = {nil, nil, {"lord", "rebel", "rebel"}}
  end

  function ev_1v2_logic:chooseGenerals()
    local room = self.room ---@type Room
    local generalNum = room.settings.generalNum
    for _, p in ipairs(room.players) do
      room:setPlayerProperty(p, "role_shown", true)
      room:broadcastProperty(p, "role")
    end

    local lord = room:getLord()
    room.current = lord
    local grace = {"ev_ruizhi&", "ev_weiguang&", "ev_shenwu&"}
    math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 6)))
    U.setPrivateMark(lord, "endian", table.random(grace, 1))
    local nonlord = room.players
    -- 地主多发俩武将
    local generals = room:getNGenerals(#nonlord * generalNum + 2)
    for i, p in ipairs(nonlord) do
      local arg = table.slice(generals, (i - 1) * generalNum + 1, i * generalNum + 1)
      if p.role == "lord" then
        local count = #generals
        table.insert(arg, generals[count])
        table.insert(arg, generals[count - 1])
      end
      p.request_data = json.encode({ arg, 1 })
      p.default_reply = arg[1]
    end
    room:notifyMoveFocus(nonlord, "AskForGeneral")
    room:doBroadcastRequest("AskForGeneral", nonlord)
    local selected = {}
    for _, p in ipairs(nonlord) do
      local general_ret
      if p.general == "" and p.reply_ready then
        general_ret = json.decode(p.client_reply)[1]
      else
        general_ret = p.default_reply
      end
      room:setPlayerGeneral(p, general_ret, true, true)
      table.insertIfNeed(selected, general_ret)
      p.default_reply = ""
    end
    generals = table.filter(generals, function(g) return not table.contains(selected, g) end)
    room:returnToGeneralPile(generals)
    for _, g in ipairs(selected) do
      room:findGeneral(g)
    end
    room:askForChooseKingdom(nonlord)

    for _, p in ipairs(nonlord) do
      room:broadcastProperty(p, "general")
    end
    room:setTag("SkipNormalDeathProcess", true)
  end


  function ev_1v2_logic:attachSkillToPlayers()
    local room = self.room
    local players = room.players
  
    local addRoleModSkills = function(player, skillName)
      local skill = Fk.skills[skillName]
      if not skill then
        fk.qCritical("Skill: "..skillName.." doesn't exist!")
        return
      end
      if skill.lordSkill then
        return
      end
      if #skill.attachedKingdom > 0 and not table.contains(skill.attachedKingdom, player.kingdom) then
        return
      end
  
      room:handleAddLoseSkills(player, skillName, nil, false)
    end
    for _, p in ipairs(room.alive_players) do
      for _, s in ipairs(Fk.generals[p.general]:getSkillNameList(false)) do
        addRoleModSkills(p, s)
      end
      if p.role == "lord" then
        local endian = U.getPrivateMark(p, "endian")
        room:setBanner("@[:]endian", endian)
        room:handleAddLoseSkills(p, endian, nil, false)
        room:handleAddLoseSkills(p, "#ev_bahu", nil, false)
      end
    end
  end

  return ev_1v2_logic
end

local m_bahu = fk.CreateTriggerSkill{
  name = "#ev_bahu",
  frequency = Skill.Compulsory,
  mute = true,
  anim_type = "drawcard",
  events = {fk.DrawNCards},
  on_use = function(self, event, target, player, data)
    data.n = data.n + 1
  end,
}

Fk:addSkill(m_bahu)

local ev_1v2_rule = fk.CreateTriggerSkill{
  name = "#ev_1v2_rule",
  priority = 0.001,
  mute = true,
  events = {fk.BuryVictim},
  can_trigger = function(self, event, target, player, data)
    return target ~= player and target.rest == 0 and target.role == "rebel" and player.role == "rebel" and not player.dead
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local choices = {"ev_1v2_draw2", "Cancel"}
    if player:isWounded() then
      table.insert(choices, 2, "ev_1v2_heal")
    end
    local choice = room:askForChoice(player, choices, self.name)
    if choice == "ev_1v2_draw2" then
      player:drawCards(2, self.name)
    else
      room:recover{ who = player, num = 1, skillName = self.name }
    end
  end,
}
Fk:addSkill(ev_1v2_rule)

local ev_1v2_mode = fk.CreateGameMode{
  name = "ev_1v2_mode",
  minPlayer = 3,
  maxPlayer = 3,
  rule = ev_1v2_rule,
  logic = ev_1v2_getLogic,
  surrender_func = function(self, playedTime)
    local surrenderJudge = { { text = "time limitation: 2 min", passed = playedTime >= 120 } }
    if Self.role ~= "lord" then
      table.insert(
        surrenderJudge,
        { text = "1v2: left you alive", passed = #table.filter(Fk:currentRoom().players, function(p) return p.rest > 0 or not p.dead end) == 2 }
      )
    end

    return surrenderJudge
  end,
  get_adjusted = function (self, player)
    if player.role == "lord" then
      return {hp = player.hp + 1, maxHp = player.maxHp + 1}
    end
    return {}
  end
}

local ev_ruizhi = fk.CreateTriggerSkill{
  name = "ev_ruizhi&",
  anim_type = "defensive",
  events = {fk.TargetConfirmed, fk.GameStart},
  can_trigger = function(self, event, target, player, data)
    if event == fk.TargetConfirmed then
      return target == player and player:hasSkill(self.name) and data.firstTarget and data.card.trueName == "slash"
    else
      return player:hasSkill(self.name)
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.TargetConfirmed then
      return player.room:askForSkillInvoke(player, self.name)
    else
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.TargetConfirmed then
      player:drawCards(1, self.name)
    else
      for _, p in ipairs(room:getOtherPlayers(player)) do
        U.viewCards(player, p:getCardIds(Player.Hand), self.name, "ev_ruizhi-view::"..p.id)
      end
    end
  end,
}

Fk:addSkill(ev_ruizhi)

Fk:addQmlMark{
  name = "weiguang_show",
  how_to_show = function(name, value, p)
    if type(value) ~= "table" then return " " end
    local suits = {}
    for _, id in ipairs(value) do
      table.insertIfNeed(suits, Fk:getCardById(id).suit)
    end
    return table.concat(table.map(suits, function(suit)
      return Fk:translate(Card.getSuitString({ suit = suit }, true))
    end), " ")
  end,
  qml_path = "packages/utility/qml/ViewPile"
}

local ev_weiguang = fk.CreateTriggerSkill{
  name = "ev_weiguang&",
  anim_type = "control",
  derived_piles = "#ev_weiguang",
  events = {fk.GameStart, fk.EventPhaseStart, fk.CardUsing},
  can_trigger = function(self, event, target, player, data)
    if event == fk.GameStart then
      return player:hasSkill(self.name)
    elseif event == fk.EventPhaseStart then
      return target == player and player:hasSkill(self.name) and player.phase == Player.Start and #player:getPile("#ev_weiguang") > 0
    elseif event == fk.CardUsing then
      if player:hasSkill(self.name) and #player:getPile("#ev_weiguang") > 0 then
        return data.card.suit == Fk:getCardById(player:getPile("#ev_weiguang")[1]).suit and target.hp <= player.hp and
        player ~= target and not target:isNude()
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      return true
    elseif event == fk.GameStart then
      return true
    elseif event == fk.CardUsing then
      return player.room:askForSkillInvoke(player, self.name, data, "#ev_weiguang-invoke::"..target.id)
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      local cids = U.askForExchange(player, self.name, player.general, player:getPile("#ev_weiguang"), player:getCardIds("he"), "#ev_weiguang-exchange", 1, true)
      if #cids > 0 then
        local cards = table.filter(cids, function (id)
          return table.contains(player:getCardIds("he"), id)
        end)
        local weiguang = table.filter(cids, function (id)
          return not table.contains(player:getCardIds("he"), id)
        end)
        U.swapCardsWithPile(player, cards, weiguang, self.name, "#ev_weiguang", true, player.id)
        room:setPlayerMark(player, "@[weiguang_show]", player:getPile("#ev_weiguang"))
      end
    elseif event == fk.GameStart then
      local card = player:drawCards(1, self.name)
      player:addToPile("#ev_weiguang", card[1], true, self.name)
      room:setPlayerMark(player, "@[weiguang_show]", player:getPile("#ev_weiguang"))
    elseif event == fk.CardUsing then
      local card = room:askForCard(target, 1, 1, true, self.name, false, ".", "#ev_weiguang-give:"..player.id)
      room:obtainCard(player.id, card[1], false, fk.ReasonGive)
    end
  end,
}

Fk:addSkill(ev_weiguang)

local ev_shenwu = fk.CreateTriggerSkill{
  name = "ev_shenwu&",
  anim_type = "offensive",
  events = {fk.EventPhaseStart, fk.DamageCaused, fk.DrawInitialCards},
  can_trigger = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      return target == player and player:hasSkill(self.name) and player.phase == Player.Start and not player:isKongcheng()
    elseif event == fk.DamageCaused then
      return target == player and player:hasSkill(self.name) and player:getMark("@@ev_shenwu-turn") > 0
    elseif event == fk.DrawInitialCards then
      return player:hasSkill(self.name) and target.role == "rebel"
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      local room = player.room
      local to = room:askForChoosePlayers(player, table.map(table.filter(room:getOtherPlayers(player), function(p)
        return player:canPindian(p) end), Util.IdMapper),
        1, 1, "#ev_shenwu-choose", self.name, true)
      if #to > 0 then
        self.cost_data = to[1]
        return true
      end
    elseif event == fk.DamageCaused or event == fk.DrawInitialCards then
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      local to = room:getPlayerById(self.cost_data)
      local pindian = player:pindian({to}, self.name)
      if pindian.results[to.id].winner == player then
        room:setPlayerMark(player, "@@ev_shenwu-turn", 1)
      else
        room:moveCardTo(pindian.results[to.id].toCard, Card.PlayerHand, player, fk.ReasonJustMove, self.name, "", true, player.id)
        room:moveCardTo(pindian.fromCard, Card.PlayerHand, to, fk.ReasonJustMove, self.name, "", true, player.id)
      end
    elseif event == fk.DamageCaused then
      data.damage = data.damage + 1
    elseif event == fk.DrawInitialCards then
      data.num = data.num - 1
    end
  end,
}

Fk:addSkill(ev_shenwu)

Fk:loadTranslationTable{
  ["ev_1v2_mode"] = "萌战斗地主",
  ["#m_bahu"] = "恩典",
  [":#m_bahu"] = "锁定技，摸牌阶段，你多摸一张牌。",
  ["#ev_1v2_rule"] = "队友阵亡补偿",
  ["ev_1v2_draw2"] = "摸两张牌",
  ["ev_1v2_heal"] = "回复1点体力",

  ["@[:]endian"] = "恩典",
  ["@[private]endian"] = "恩典",
  ["ev_ruizhi&"] = "睿智",
  [":ev_ruizhi&"] = "游戏开始时，你观看所有其他角色的手牌。当你成为其他角色使用【杀】的目标后，你可摸一张牌。",
  ["ev_ruizhi-view"] = "正在观看%dest的手牌",
  ["ev_weiguang"] = "威光",
  ["#ev_weiguang"] = "威光",
  ["ev_weiguang&"] = "威光",
  ["@ev_weiguang"] = "威光",
  ["@[weiguang_show]"] = "威光",
  [":ev_weiguang&"] = "游戏开始时，你摸一张牌并将此牌明置于恩典牌上。准备阶段，你选择是否用一张牌替换“威光”牌。其他角色使用与“威光”牌花色相同的牌时，若其体力值不大于你，你可令其将一张牌交给你。",
  ["#ev_weiguang-invoke"] = "威光：你可以令%dest交给你一张牌",
  ["#ev_weiguang-exchange"] = "威光：你可以用一张牌替换“威光”牌",
  ["#ev_weiguang-give"] = "威光：请选择交给%src的牌",
  ["ev_shenwu&"] = "神武",
  [":ev_shenwu&"] = "其他角色的起始手牌数-1。准备阶段，你可与一名其他角色拼点；若你赢，则你于本回合内造成伤害时，令此伤害+1；若你没赢，你与其各获得对方拼点的牌。",
  ["#ev_shenwu-choose"] = "神武：你可与一名其他角色拼点",
  ["@@ev_shenwu-turn"] = "神武拼赢",

  ["time limitation: 2 min"] = "游戏时长达到2分钟",
  ["1v2: left you alive"] = "仅剩你和地主存活",

  [":ev_1v2_mode"] = desc_1v2,
}

return ev_1v2_mode
